package server;

import java.io.IOException;
import javax.net.ssl.SSLSocket;
import common.Lector_socket;
import common.Mensaje;

/**
 * Clase que atiende al cliente admin (a pesar del nombre no extiende a thread)
 * @author Matias
 *
 */
public class ThreadServerAdmin {

	private static final int TIME_OUT_CIERRE= 3000;

	private SSLSocket conexion_entrante;
	private ServidorPrincipal server;
	private Lector_socket lector;

	private int estado_interno;

	private Log log;

	/**
	 * Constructor de la clase. Recibe el socketSSL que utilza como conexión y el servidor ppal al que esta vinculado.
	 * @param s : socket SSL
	 * @param serv : servidor al que está vinculado
	 */
	public ThreadServerAdmin(SSLSocket s, ServidorPrincipal serv, Log l){
		log = l;
		conexion_entrante=s;
		server = serv;
		lector = new Lector_socket(conexion_entrante);
		log.writeLog(Log.INFO, "CLIENTE ADMIN", "Constructor", "Se creo instancia de thread para atender al admin");
	}

	public void atender_admin(){

		boolean fin=server.get_fin_sesion();
		while(!fin){

			Mensaje msj = lector.leer_msj();

			if(msj!=null){ // es decir, si no se cortó la conexión

				estado_interno = server.get_estado();
				Mensaje rta=new Mensaje();

				switch(estado_interno){

				case 0:{
					// momento en que se crean los threads para atender al admin y clientes 
					break;
				}
				case 1 : {
					//Se espera por msj de inicio de sesión
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_INICIO_SESION)){ // si recibe inicio de sesión devuelve OK

						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido("The hammer of the gods\nwill drive our ships to new lands\nto fight the horde, singing an criying\nValhalla i'm comming!!!\n by Led Zeppelin");// ESTO ES UNA PRUEBA!!!!!!!!!!!!!!

						server.setSesionActual();
						server.set_estado(2);
						log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 1", "Se da comienzo a la sesión");

					}else{ // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);
						rta.setContenido("ERROR en estado 1\n\tse espera msj del tipo 'INICIO SESION'\n\t bye!");// ESTO ES UNA PRUEBA!!!!!!!!!!!!!!

					}
					break;}
				case 2 : {
					// verificación de quorúm 
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_FIN_ADMISION_CLIENTES)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						synchronized (server) {
							server.notify();
						}
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_QUORUM)){
						if(server.hayQuorum()){
							rta.setTipo_msj(Mensaje.TIPO_SI);
							server.set_estado(3);
							log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 2", "Hay quórum");

						}else{// en caso de que no se alcance quorum se pasa a estado 8
							rta.setTipo_msj(Mensaje.TIPO_NO);
							server.set_estado(8); // se cierra sesion
							rta.setContenido(server.cantClientesConectados()+"");
							// AGREGAR CANT DE ASAMBLEISTAS!!!!!
							log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 2", "NO hay quórum");
						}

					}else{ // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);

					}
					break;
				}
				case 3 : {
					// Inicia tema 
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_INICIO_TEMA)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						server.definirTemaActual(msj.getContenido());

						synchronized (this) {
							try {
								this.wait();
							} catch (InterruptedException e) {
								System.err.println(e.getMessage());
							}
						}

						server.set_estado(4);
						log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 3", "Se da inicio a tema");

					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){ // admin pregunta si ya estan los rtdos, se le responde que NO
						rta.setTipo_msj(Mensaje.TIPO_NO);

					}else{ // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);
					}
					break;
				}
				case 4 : {// ???????????????????????????????????????????????????????
					// che, y ac� que hacemos??? bueno... si pregunta por votaci�n respondemos uqe s�, cualquier otra cosa respondemos error
					// IMPORTANTE: server gral es responsable de pasar a siguiente estado
					//*msj = lector.leer_msj();
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						//rta.setContenido(server.cantClientesConectados()+"");
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_VOTACION)){ // admin pregunta si ahora hay votación, se le responde que SI---PUEDE QUE ESTE DE MAS!!!!!!!!!
						rta.setTipo_msj(Mensaje.TIPO_NO);
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){ // admin pregunta si ya estan los rtdos, se le responde que NO
						rta.setTipo_msj(Mensaje.TIPO_NO);
					}else{ // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);
					}
					break;
				}
				case 5 : {
					// IMPORTANTE: server gral es responsable de pasar a estado 6 tras terminar de procesar votos
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_VOTACION)){ // admin pregunta si ahoa hay votaci�n, se le responde que SI
						rta.setTipo_msj(Mensaje.TIPO_SI);
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){ // admin pregunta si ya estan los rtdos, se le responde que NO
						rta.setTipo_msj(Mensaje.TIPO_NO);
					}else{ // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);
					}

					break;}
				case 6 : {
					// IMPORTANTE: server ppal responsable por pasara estado 7
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){
						synchronized (this) {
							try {
								while(!server.hayRtdos){ // bloqueo el thread hasta que server ppal termine de procesar los rtdos
									this.wait();
								}
							} catch (InterruptedException e) {}
						}
						rta.setTipo_msj(Mensaje.TIPO_SI);
						rta.setContenido(server.obtenerRtdos());
						server.set_estado(7);
					}else{ // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);
						System.out.println("E6: error sobre admin");
					}
					break;}
				case 7:{
					if(msj.getTipo_msj().equals(Mensaje.TIPO_CANT_ASAMBLEISTAS)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						rta.setContenido(server.nbresClientesConectados());
					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_NUEVO_TEMA)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						server.set_estado(3);
						log.writeLog(Log.INFO, "CLIENTE ADMIN", "Estado 7", "Inicia nuevo tema");

					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_CIERRE_SESION)){
						rta.setTipo_msj(Mensaje.TIPO_OK);
						server.set_estado(8);
						log.writeLog(Log.INFO, "CLIENTE ADMIN", "Estado 7", "Cierra sesión");

					}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_VOTACION)){
						rta.setTipo_msj(Mensaje.TIPO_NO_HAY_QUORUM);
						rta.setContenido(server.cantClientesConectados()+"");
						
					}else { // cualquier otro msj lo considera error
						rta.setTipo_msj(Mensaje.TIPO_ERROR);
					}
					break;
				}
				case 8:{
					rta.setTipo_msj(Mensaje.TIPO_CIERRE_SESION);

					// cierre de conexion
					fin = true;

					break;
				}
				} // fin-switch

				lector.enviar_msj(rta);


			}else{ // else de if(msj!=null) es decir, se corto la conexión!
				fin = true;
				log.writeLog(Log.INFO, "CLIENTE ADMIN", "Estado 8", "Se cortó la conexión, se procederá a cerrar la conexión");
				server.set_estado(8);
			}

		} // fin-while

		// --- CIERRE CONEXION ---
		// sleep para dar tiempo a que cliente reciba la rta
		try {
			Thread.sleep(TIME_OUT_CIERRE);
		} catch (InterruptedException e) {
		}

		lector.cerrar();

		try {
			conexion_entrante.close();
		} catch (IOException e) {
		}
		log.writeLog(Log.INFO, "CLIENTE ADMIN", "Cierre conexión", "Se cerró la conexión correctamente");
	} // fin-atender-admin()

}